package values

import (
	"encoding/json"
	"errors"
	"fmt"
	"reflect"
	"strings"
	"time"
)

// ToMapAny 转换目标为 map[K]any , 如果转换失败, 则返回空的map
//   - 通过断言快速处理基本切片 map[TypeBase]any
//   - 其他类型Map尝试反射检查后处理
//   - TypeBase: string | bool | int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration| time.Month | time.Weekday
func ToMapAny[K TypeBase](v any) map[K]any {
	if v == nil {
		return map[K]any{}
	}
	to, _ := ToMapAnyE[K](v)
	return to
}

// ToMapAnyD 转换目标为 map[K]any , 如果转换失败, 则返回defaultVal指定的map
//   - 通过断言快速处理基本切片 map[TypeBase]any
//   - 其他类型Map尝试反射检查后处理
//   - TypeBase: string | bool | int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration| time.Month | time.Weekday
func ToMapAnyD[K TypeBase](v any, defaultVal map[K]any) map[K]any {
	if v == nil {
		return defaultVal
	}
	if to, err := ToMapAnyE[K](v); err == nil {
		return to
	}
	return defaultVal
}

// ToMapAnyE 转换目标为 map[K]any, 如果转换失败, 则返回空的map和错误信息
//   - 通过断言快速处理基本切片 map[TypeBase]any
//   - 其他类型Map尝试反射检查后处理
//   - TypeBase: string | bool |	int | int8 | int16 | int32 | int64 |	uint | uint8 | uint16 | uint32 | uint64 |	float32 | float64 |	time.Time | time.Duration| time.Month | time.Weekday
func ToMapAnyE[K TypeBase](v any) (map[K]any, error) {
	toVal := map[K]any{}
	if v == nil {
		return toVal, errors.New("ToMapAnyE: nil pointer not support")
	}
	// 先通过断言判断待转换值是否为 map[K]any / map[any]any 类型
	switch vs := v.(type) {
	case map[K]any:
		return _toMapAnyAppend(vs)
	case *map[K]any:
		return _toMapAnyAppend(*vs)
	case map[any]any:
		return _toMapAnyKV[K](vs)
	case *map[any]any:
		return _toMapAnyKV[K](*vs)
	case string:
		if vs != "" && strings.HasPrefix(vs, "{") && strings.HasSuffix(vs, "}") && json.Valid([]byte(vs)) {
			var toAny map[K]any
			if err := json.Unmarshal([]byte(vs), &toAny); err == nil {
				return toAny, nil
			} else {
				return toVal, fmt.Errorf("ToMapAnyE: string type to map[K]any type, failed to unmarshal JSON: %s", err.Error())
			}
		}
		return toVal, errors.New("ToMapAnyE: string type to map[K]any type not support")
	case *string:
		if *vs != "" && strings.HasPrefix(*vs, "{") && strings.HasSuffix(*vs, "}") && json.Valid([]byte(*vs)) {
			var toAny map[K]any
			if err := json.Unmarshal([]byte(*vs), &toAny); err == nil {
				return toAny, nil
			} else {
				return toVal, fmt.Errorf("ToMapAnyE: *string type to map[K]any type, failed to unmarshal JSON: %s", err.Error())
			}
		}
		return toVal, errors.New("ToMapAnyE: *string type to map[K]any type not support")
	}
	// 如果待转换值是Golang 常用的基本类型或指针, 则返回错误信息
	if _isTypeBasic(v) {
		return toVal, fmt.Errorf("ToMapAnyE: %T type to map[K]any type not support", v)
	}
	// 通过断言判断待转换值是否为 map[X]X 类型
	if toVal, err, next := _toMapAnyWithKey[K, string](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, int](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, uint](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, int64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, uint64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, int32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, uint32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, int16](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, uint16](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, int8](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, uint8](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, float32](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, float64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, float64](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, time.Time](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, time.Duration](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, time.Month](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, time.Weekday](v); !next {
		return toVal, err
	}
	if toVal, err, next := _toMapAnyWithKey[K, bool](v); !next {
		return toVal, err
	}

	// [4] 尝试反射检查是否为Map类型
	return _toMapAnyReflect[K](v)

}

func _toMapAnyAppend[K TypeBase](vs map[K]any) (map[K]any, error) {
	if vs == nil {
		return map[K]any{}, errors.New("ToMapAnyE: nil pointer not support")
	}
	if len(vs) == 0 {
		return map[K]any{}, nil
	}
	toVal := make(map[K]any, len(vs))
	for key, val := range vs {
		toVal[key] = val
	}
	return toVal, nil
}
func _toMapAnyKV[K TypeBase](vs map[any]any) (map[K]any, error) {
	if vs == nil {
		return map[K]any{}, errors.New("ToMapAnyE: nil pointer not support")
	}
	if len(vs) == 0 {
		return map[K]any{}, nil
	}
	toVal := make(map[K]any, len(vs))
	var toK K
	for key, item := range vs {
		if val, ok := key.(K); ok {
			toK = val
		} else if val, err := ToBaseE[K](key); err == nil {
			toK = val
		} else {
			return map[K]any{}, fmt.Errorf("ToMapAnyE: K[%#v] to type of %T, error:%s", key, toK, err.Error())
		}
		toVal[toK] = item
	}
	return toVal, nil
}
func _toMapAnyWithKey[K TypeBase, Key TypeBase](v any) (map[K]any, error, bool) {
	switch vs := v.(type) {
	default:
		return map[K]any{}, nil, true // Next "true" To continue
	case map[Key]any:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]string:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]bool:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]int:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]int8:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]int16:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]int32:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]int64:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]uint:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]uint8:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]uint16:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]uint32:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]uint64:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]float32:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]float64:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]time.Time:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]time.Duration:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]time.Weekday:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]time.Month:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]json.Number:
		return _toMapAnyWithLoop[K](vs)
	case map[Key]error:
		return _toMapAnyWithLoop[K](vs)
	case *map[Key]any:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]string:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]bool:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]int:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]int8:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]int16:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]int32:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]int64:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]uint:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]uint8:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]uint16:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]uint32:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]uint64:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]float32:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]float64:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]time.Time:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]time.Duration:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]time.Weekday:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]time.Month:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]json.Number:
		return _toMapAnyWithLoop[K](*vs)
	case *map[Key]error:
		return _toMapAnyWithLoop[K](*vs)
	}
}
func _toMapAnyWithLoop[K TypeBase, vsK TypeBase, vsV any](vs map[vsK]vsV) (map[K]any, error, bool) {
	if vs == nil {
		return map[K]any{}, errors.New("ToMapAnyE: nil pointer not support"), false // Next "false" To Break
	}
	if len(vs) == 0 {
		return map[K]any{}, nil, false // Next "false" To Break
	}
	toVal := make(map[K]any, len(vs))
	var toK K
	for key, item := range vs {
		if val, ok := any(key).(K); ok {
			toK = val
		} else if val, err := ToBaseE[K](key); err == nil {
			toK = val
		} else {
			return map[K]any{}, fmt.Errorf("ToMapAnyE: K[%#v] to type of %T, error:%s", key, toK, err.Error()), false // Next "false" To Break
		}
		toVal[toK] = any(item)
	}
	return toVal, nil, false // Next "false" To Break
}

// [4] 尝试反射检查是否为Map类型
func _toMapAnyReflect[K TypeBase](v any) (map[K]any, error) {
	// 获取输入值的反射类型和值
	vType := reflect.TypeOf(v)
	vValue := reflect.ValueOf(v)
	if vType.Kind() == reflect.Ptr {
		if vValue.IsNil() {
			return map[K]any{}, errors.New("ToMapAnyE: input is a nil pointer")
		}
		vType = vType.Elem()
		vValue = vValue.Elem()
	}
	// 检查是否为Map
	if vType.Kind() != reflect.Map {
		return map[K]any{}, fmt.Errorf("ToMapAnyE: unsupported type %T, expected map", v)
	}
	// 如果长度为0，直接返回空Map
	if vValue.Len() == 0 {
		return map[K]any{}, nil
	}
	toVal := make(map[K]any, vValue.Len())
	// 遍历 Map 的键值对
	mapKeys := vValue.MapKeys()
	for _, keyRef := range mapKeys {
		// 获取Map的键和值
		if key, err := ToBaseE[K](keyRef.Interface()); err == nil {
			toVal[key] = vValue.MapIndex(keyRef).Interface()
		} else {
			var toK K
			return toVal, fmt.Errorf("ToMapAnyE: K[%#v] to type of %T, error:%s", key, toK, err.Error())
		}
	}
	return toVal, nil
}
